package org.mybatis.generator.plugins;

import static org.mybatis.generator.internal.util.StringUtility.stringHasValue;

import org.apache.log4j.Logger;

import java.util.ArrayList;
import java.util.List;

import org.mybatis.generator.api.GeneratedJavaFile;
import org.mybatis.generator.api.GeneratedJavaScriptFile;
import org.mybatis.generator.api.GeneratedXmlFile;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.OutputUtilities;
import org.mybatis.generator.api.dom.java.Field;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.Interface;
import org.mybatis.generator.api.dom.java.JavaVisibility;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.Parameter;
import org.mybatis.generator.api.dom.java.TopLevelClass;
import org.mybatis.generator.api.dom.xml.Attribute;
import org.mybatis.generator.api.dom.xml.Document;
import org.mybatis.generator.api.dom.xml.Element;
import org.mybatis.generator.api.dom.xml.TextElement;
import org.mybatis.generator.api.dom.xml.XmlElement;
import org.mybatis.generator.codegen.XmlConstants;
import org.mybatis.generator.codegen.mybatis3.Ibatis2FormattingUtilities;
import org.mybatis.generator.codegen.mybatis3.MyBatis3FormattingUtilities;
import org.mybatis.generator.internal.rules.Rules;
import org.mybatis.generator.internal.util.StringUtility;

/**
 * 增加公用条件查询类 BaseQo
 * 
 * @author QQ:34847009
 * @date 2010-10-21 下午09:33:48
 */
public class MybatisQueryObjectPlugin extends PluginAdapter {
	/**
	 * Logger for this class
	 */
	private static final Logger logger = Logger
			.getLogger(MybatisQueryObjectPlugin.class);

	private FullyQualifiedJavaType queryObjectType;
	/** 数据库类型 */
	private String databaseType;

	/**
	 * 是否把所有条件就设置到一个里面
	 */
	private boolean isAllInOne;

	@Override
	public boolean validate(List<String> warnings) {
		databaseType = context.getJdbcConnectionConfiguration()
				.getDriverClass();
		if (stringHasValue(properties.getProperty("isAllInOne"))) { //$NON-NLS-1$
			isAllInOne = StringUtility.isTrue(properties
					.getProperty("isAllInOne"));
		} else {
			isAllInOne = false;
		}
		return true;
	}

	@Override
	public List<GeneratedJavaFile> contextGenerateAdditionalJavaFiles(
			IntrospectedTable introspectedTable) {
		String queryObject = context.getJavaModelGeneratorConfiguration()
				.getTargetPackage();
		queryObject = queryObject.replace(".po.", ".qo.");
		int qoIndex = queryObject.lastIndexOf(".qo.");
		queryObject = queryObject.substring(0, qoIndex + 3) + ".BaseQo";
		queryObjectType = new FullyQualifiedJavaType(queryObject);

		List<GeneratedJavaFile> files = new ArrayList<GeneratedJavaFile>();
		TopLevelClass topLevelClass = new TopLevelClass(queryObject);
		topLevelClass.setVisibility(JavaVisibility.PUBLIC);
		addClassComment(topLevelClass, "公用条件查询类");
		topLevelClass.addImportedType(FullyQualifiedJavaType
				.getNewMapInstance());
		topLevelClass.addImportedType(FullyQualifiedJavaType
				.getNewHashMapInstance());

		FullyQualifiedJavaType types = new FullyQualifiedJavaType(
				"java.util.Map<java.lang.String, java.lang.Object>");
		Rules rules = introspectedTable.getRules();
		if (rules.generateUpdateByExampleSelective()
				|| rules.generateUpdateByExampleWithBLOBs()
				|| rules.generateUpdateByExampleWithoutBLOBs()) {
			Method method = new Method();
			method.setVisibility(JavaVisibility.PROTECTED);
			method.setConstructor(true);
			method.setName(queryObjectType.getShortName());
			method.addParameter(new Parameter(queryObjectType, "qo")); //$NON-NLS-1$
			method.addBodyLine("this.orderByClause = qo.orderByClause;"); //$NON-NLS-1$
			method.addBodyLine("this.condition = qo.condition;"); //$NON-NLS-1$
			method.addBodyLine("this.distinct = qo.distinct;"); //$NON-NLS-1$
			method.addBodyLine("this.pageNumber = qo.pageNumber;"); //$NON-NLS-1$
			method.addBodyLine("this.pageSize = qo.pageSize;"); //$NON-NLS-1$
			topLevelClass.addMethod(method);
		}

		Field field = new Field();
		field.setVisibility(JavaVisibility.PRIVATE);
		field.setType(types);
		field.setName("condition"); //$NON-NLS-1$
		addFieldComment(field, "存放条件查询值");
		topLevelClass.addField(field);

		// add field, getter, setter for distinct
		field = new Field();
		field.setVisibility(JavaVisibility.PROTECTED);
		field.setType(FullyQualifiedJavaType.getBooleanPrimitiveInstance());
		field.setName("distinct"); //$NON-NLS-1$
		addFieldComment(field, "是否相异");
		topLevelClass.addField(field);

		// add field, getter, setter for pageSize
		field = new Field();
		field.setVisibility(JavaVisibility.PROTECTED);
		field.setType(FullyQualifiedJavaType.getInteger());
		field.setName("pageSize=10"); //$NON-NLS-1$
		addFieldComment(field, "每页记录数(默认10条每页)");
		topLevelClass.addField(field);

		// add field, getter, setter for pageNumber
		field = new Field();
		field.setVisibility(JavaVisibility.PROTECTED);
		field.setType(FullyQualifiedJavaType.getInteger());
		field.setName("pageNumber = 1"); //$NON-NLS-1$
		addFieldComment(field, "当前页码(默认第一页)");
		topLevelClass.addField(field);

		// add field, getter, setter for distinct
		field = new Field();
		field.setVisibility(JavaVisibility.PROTECTED);
		field.setType(FullyQualifiedJavaType.getInteger());
		field.setName("totalSize = 0"); //$NON-NLS-1$
		addFieldComment(field, "记录数");
		topLevelClass.addField(field);

		// add field, getter, setter for queryType
		field = new Field();
		field.setVisibility(JavaVisibility.PROTECTED);
		field.setType(FullyQualifiedJavaType.getInteger());
		field.setName("queryType"); //$NON-NLS-1$
		addFieldComment(field, "查询类型");
		topLevelClass.addField(field);

		// add field, getter, setter for orderby clause
		field = new Field();
		field.setVisibility(JavaVisibility.PROTECTED);
		field.setType(FullyQualifiedJavaType.getStringInstance());
		field.setName("orderByClause"); //$NON-NLS-1$
		addFieldComment(field, "排序字段");
		topLevelClass.addField(field);

		Method method = new Method();
		method.setVisibility(JavaVisibility.PUBLIC);
		method.setConstructor(true);
		method.setName("BaseQo"); //$NON-NLS-1$
		method.addBodyLine("condition = new HashMap<String, Object>();"); //$NON-NLS-1$
		topLevelClass.addMethod(method);

		method = new Method();
		method.setVisibility(JavaVisibility.PUBLIC);
		method.setName("clear"); //$NON-NLS-1$
		method.addBodyLine("condition.clear();"); //$NON-NLS-1$
		method.addBodyLine("orderByClause = null;"); //$NON-NLS-1$
		method.addBodyLine("distinct = false;"); //$NON-NLS-1$
		method.addBodyLine("this.pageNumber = 1;"); //$NON-NLS-1$
		method.addBodyLine("this.pageSize = 10;"); //$NON-NLS-1$
		topLevelClass.addMethod(method);

		method = new Method();
		method.setVisibility(JavaVisibility.PUBLIC);
		method.setReturnType(queryObjectType);
		method.setName("put"); //$NON-NLS-1$
		method.addParameter(new Parameter(FullyQualifiedJavaType
				.getStringInstance(), "condition")); //$NON-NLS-1$
		method.addParameter(new Parameter(FullyQualifiedJavaType
				.getObjectInstance(), "value")); //$NON-NLS-1$
		method.addBodyLine("this.condition.put(condition, value);"); //$NON-NLS-1$
		method.addBodyLine("return (BaseQo) this;"); //$NON-NLS-1$
		addSetterComment(method, OutputUtilities.lineSeparator
				+ "\t *            查询的条件名称" + OutputUtilities.lineSeparator
				+ "\t * @param value" + OutputUtilities.lineSeparator
				+ "\t *            查询的值", "condition");
		topLevelClass.addMethod(method);

		method = new Method();
		method.setVisibility(JavaVisibility.PUBLIC);
		method.setName("setOrderByClause"); //$NON-NLS-1$
		method.addParameter(new Parameter(FullyQualifiedJavaType
				.getStringInstance(), "orderByClause")); //$NON-NLS-1$
		method.addBodyLine("this.orderByClause = orderByClause;"); //$NON-NLS-1$
		addSetterComment(method, OutputUtilities.lineSeparator
				+ "\t *            排序字段", "orderByClause");
		topLevelClass.addMethod(method);

		method = new Method();
		method.setVisibility(JavaVisibility.PUBLIC);
		method.setName("setQueryType"); //$NON-NLS-1$
		method.addParameter(new Parameter(FullyQualifiedJavaType.getInteger(),
				"queryType")); //$NON-NLS-1$
		method.addBodyLine("this.queryType = queryType;"); //$NON-NLS-1$
		addSetterComment(method, OutputUtilities.lineSeparator
				+ "\t *            查询类型", "queryType");
		topLevelClass.addMethod(method);

		method = new Method();
		method.setVisibility(JavaVisibility.PUBLIC);
		method.setName("setDistinct"); //$NON-NLS-1$
		method.addParameter(new Parameter(FullyQualifiedJavaType
				.getBooleanPrimitiveInstance(), "distinct")); //$NON-NLS-1$
		method.addBodyLine("this.distinct = distinct;"); //$NON-NLS-1$
		addSetterComment(method, OutputUtilities.lineSeparator
				+ "\t *            是否相异", "distinct");
		topLevelClass.addMethod(method);

		method = new Method();
		method.setVisibility(JavaVisibility.PUBLIC);
		method.setName("setCondition"); //$NON-NLS-1$
		method.addParameter(new Parameter(types, "condition")); //$NON-NLS-1$
		method.addBodyLine("this.condition = condition;"); //$NON-NLS-1$
		method.addDeprecated();
		topLevelClass.addMethod(method);

		method = new Method();
		method.setVisibility(JavaVisibility.PUBLIC);
		method.setReturnType(types);
		method.setName("getCondition"); //$NON-NLS-1$
		method.addBodyLine("return condition;"); //$NON-NLS-1$
		method.addDeprecated();
		topLevelClass.addMethod(method);

		method = new Method();
		method.setVisibility(JavaVisibility.PUBLIC);
		method.setName("setPageNumber"); //$NON-NLS-1$
		method.addParameter(new Parameter(FullyQualifiedJavaType.getInteger(),
				"pageNumber")); //$NON-NLS-1$
		method.addBodyLine("this.pageNumber = pageNumber;"); //$NON-NLS-1$
		addSetterComment(method, OutputUtilities.lineSeparator
				+ "\t *            指定返回记录行的偏移量<br>"
				+ OutputUtilities.lineSeparator + "\t *            "
				+ "pageNumber= 1,pageSize=10;  // 检索记录行 1-10", "pageNumber");
		topLevelClass.addMethod(method);

		method = new Method();
		method.setVisibility(JavaVisibility.PUBLIC);
		method.setReturnType(FullyQualifiedJavaType.getInteger());
		method.setName("getPageNumber"); //$NON-NLS-1$
		method.addBodyLine("return pageNumber;"); //$NON-NLS-1$
		method.addDeprecated();
		topLevelClass.addMethod(method);

		method = new Method();
		method.setVisibility(JavaVisibility.PUBLIC);
		method.setName("setPageSize"); //$NON-NLS-1$
		method.addParameter(new Parameter(FullyQualifiedJavaType.getInteger(),
				"pageSize")); //$NON-NLS-1$
		method.addBodyLine("this.pageSize = pageSize;"); //$NON-NLS-1$
		addSetterComment(method, OutputUtilities.lineSeparator
				+ "\t *            指定返回记录行的最大数目" + "<br>"
				+ OutputUtilities.lineSeparator
				+ "\t *            mysqlOffset= 5,pageSize=10;  // 检索记录行 6-15",
				"mysqlLength");
		addSetterComment(method, OutputUtilities.lineSeparator
				+ "\t *            指定返回记录行的最大数目<br>"
				+ OutputUtilities.lineSeparator + "\t *            "
				+ "pageNumber= 1,pageSize=10;  // 检索记录行 1-10", "pageSize");
		topLevelClass.addMethod(method);

		method = new Method();
		method.setVisibility(JavaVisibility.PUBLIC);
		method.setReturnType(FullyQualifiedJavaType.getInteger());
		method.setName("getPageSize"); //$NON-NLS-1$
		method.addBodyLine("return pageSize;"); //$NON-NLS-1$
		method.addDeprecated();
		topLevelClass.addMethod(method);

		method = new Method();
		method.setVisibility(JavaVisibility.PUBLIC);
		method.setReturnType(FullyQualifiedJavaType.getInteger());
		method.setName("getTotalSize"); //$NON-NLS-1$
		method.addBodyLine("return totalSize;"); //$NON-NLS-1$
		method.addDeprecated();
		topLevelClass.addMethod(method);

		method = new Method();
		method.setVisibility(JavaVisibility.PUBLIC);
		method.setName("setTotalSize"); //$NON-NLS-1$
		method.addParameter(new Parameter(types, "totalSize")); //$NON-NLS-1$
		method.addBodyLine("this.totalSize = totalSize;"); //$NON-NLS-1$
		method.addDeprecated();
		topLevelClass.addMethod(method);

		// 增加结束处

		//cjianquan 2020/3/24 BaseQo.java 不生成。
//		GeneratedJavaFile file = new GeneratedJavaFile(topLevelClass, context.getJavaModelGeneratorConfiguration().getTargetProject());
//		files.add(file);
		return files;
	}

	@Override
	public boolean clientGenerated(Interface interfaze,
			TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
		// 接口方法
		List<Method> methods = interfaze.getMethods();
		FullyQualifiedJavaType types = new FullyQualifiedJavaType(
				"java.util.Map<java.lang.String, java.lang.Object>");
		Parameter parameter = new Parameter(types, "condition",
				"@Param(\"condition\")");
		Parameter parameter2 = new Parameter(queryObjectType, "example");
		interfaze.addImportedType(FullyQualifiedJavaType.getNewMapInstance());
		boolean first = true;
		for (int i = 0; i < methods.size(); i++) {
			Method method = methods.get(i);
			if (method.getFormattedContent(0, true).contains("Example")) {
				int size = method.getParameters().size();
				if (first) {
					interfaze.removeImportedType(new FullyQualifiedJavaType(
							introspectedTable.getExampleType()));
					interfaze.addImportedType(queryObjectType);
				}
				if (size == 1) {
					method.removeParameter(0);
					if (isAllInOne) {
						method.addParameter(parameter);
					} else {
						method.addParameter(parameter2);
					}
				} else if (size == 2) {
					method.removeParameter(1);
					method.addParameter(1, parameter);
				}
				first = false;
			}
		}

		return true;
	}

	@Override
	public boolean sqlMapDocumentGenerated(Document document,
			IntrospectedTable introspectedTable) {
		// 移除第2个
		// document.getRootElement().getElements().remove(2);

		// 替换所有条件parameterType中的pojoExample
		List<Element> list = document.getRootElement().getElements();
		// logger.info(list.size() + "");

		String tableName = introspectedTable.getFullyQualifiedTable()
				.toString();
		if (tableName != null && tableName.length() > 0) {
			tableName = tableName.replaceFirst(tableName.substring(0, 1),
					tableName.substring(0, 1).toUpperCase());
		} else {
			System.out
					.println("**********************表名为空**********************");
		}

		while (tableName.lastIndexOf("_") != -1) {
			int index = tableName.lastIndexOf("_");
			tableName = tableName.replaceFirst(
					"_" + tableName.substring(index + 1, index + 2), tableName
							.substring(index + 1, index + 2).toUpperCase());
		}

		String qoName = context.getJavaModelGeneratorConfiguration()
				.getTargetPackage() + "." + tableName;
		if (qoName != null && qoName.length() > 0) {
			qoName = qoName.replace(".po.", ".qo.");
			qoName = util.StringUtils.replaceLast(qoName,"Po","Qo");
		}

		FullyQualifiedJavaType qo = new FullyQualifiedJavaType(qoName);

		for (int i = 0; i < list.size(); i++) {
			XmlElement xml = (XmlElement) list.get(i);
			String content = xml.getFormattedContent(0);
			if (content.contains("selectBy" + tableName)) {
				List<Attribute> attrs = xml.getAttributes();
				for (int j = 0; j < attrs.size(); j++) {
					if (attrs.get(j).getName().equals("parameterType")) {
						attrs.get(j).setValue(qo.getFullyQualifiedName());
					}
				}
			} else if (content.contains("selectPageBy" + tableName)) {
				List<Attribute> attrs = xml.getAttributes();
				for (int j = 0; j < attrs.size(); j++) {
					if (attrs.get(j).getName().equals("parameterType")) {
						attrs.get(j).setValue(qo.getFullyQualifiedName());
					}
				}
			} else if (content.contains("deleteBy" + tableName)) {
				List<Attribute> attrs = xml.getAttributes();
				for (int j = 0; j < attrs.size(); j++) {
					if (attrs.get(j).getName().equals("parameterType")) {
						attrs.get(j).setValue(qo.getFullyQualifiedName());
					}
				}
			} else if (content.contains("countBy" + tableName)) {
				List<Attribute> attrs = xml.getAttributes();
				for (int j = 0; j < attrs.size(); j++) {
					if (attrs.get(j).getName().equals("parameterType")) {
						attrs.get(j).setValue(qo.getFullyQualifiedName());
					}
				}
			} else if (content.contains("updateBy" + tableName + "Selective")) {
				List<Attribute> attrs = xml.getAttributes();
				for (int j = 0; j < attrs.size(); j++) {
					if (attrs.get(j).getName().equals("parameterType")) {
						attrs.get(j).setValue(qo.getFullyQualifiedName());
					}
				}
			} else if (content.contains("updateBy" + tableName)) {
				List<Attribute> attrs = xml.getAttributes();
				for (int j = 0; j < attrs.size(); j++) {
					if (attrs.get(j).getName().equals("parameterType")) {
						attrs.get(j).setValue(qo.getFullyQualifiedName());
					}
				}
			}

			/**
			 * if (content.contains(introspectedTable.getExampleType())) {
			 * List<Attribute> attrs = xml.getAttributes(); for (int j = 0; j <
			 * attrs.size(); j++) { if
			 * (attrs.get(j).getName().equals("parameterType")) {
			 * attrs.get(j).setValue(qo.getFullyQualifiedName()); } } } else
			 */
			if (content.contains("Update_By_" + tableName + "_Where_Clause")) {
				if (xml.getElements().size() == 3) {
					xml = (XmlElement) xml.getElements().get(2);
					xml = (XmlElement) xml.getElements().get(0);
					xml.getAttributes().get(0)
							.setValue(tableName + "_Where_Clause");
				} else {
					for (int j = 0; j < xml.getElements().size(); j++) {
						Element xmls = xml.getElements().get(j);
						if (xmls.getFormattedContent(0).contains(
								"Update_By_" + tableName + "_Where_Clause")) {
							xml = (XmlElement) xmls;
							xml = (XmlElement) xml.getElements().get(0);
							xml.getAttributes().get(0)
									.setValue(tableName + "_Where_Clause");
						}
					}
				}
			}

		}

		for (int i = 0; i < list.size(); i++) {
			XmlElement xml = (XmlElement) list.get(i);
			String content = xml.getFormattedContent(0);

			/** 修改 super_dev_001 */
			if (content.contains("updateBy" + tableName + "Selective")) {
				List<Attribute> attrs = xml.getAttributes();
				for (int j = 0; j < attrs.size(); j++) {
					if (attrs.get(j).getName().equals("parameterType")) {
						attrs.get(j).setValue(qo.getFullyQualifiedName());
					}
				}
			} else if (content.contains("updateBy" + tableName)) {
				List<Attribute> attrs = xml.getAttributes();
				for (int j = 0; j < attrs.size(); j++) {
					if (attrs.get(j).getName().equals("parameterType")) {
						attrs.get(j).setValue(qo.getFullyQualifiedName());
					}
				}
			}

		}

		// Example_Where_Clause
		XmlElement Where_Clause = (XmlElement) document.getRootElement()
				.getElements().get(1);
		// 移除第一个
		Where_Clause.removeElement(0);

		StringBuilder sb = new StringBuilder();
		XmlElement dynamicElement = new XmlElement("trim"); //$NON-NLS-1$
		dynamicElement.addAttribute(new Attribute("prefix", "where")); //$NON-NLS-1$ //$NON-NLS-2$
		dynamicElement.addAttribute(new Attribute("prefixOverrides", "and|or")); //$NON-NLS-1$ //$NON-NLS-2$
		Where_Clause.addElement(dynamicElement);

		for (IntrospectedColumn introspectedColumn : introspectedTable
				.getAllColumns()) {

			if (! (introspectedColumn.getJdbcTypeName().equals("TIMESTAMP") || introspectedColumn.getJdbcTypeName().equals("DATE")) ) {
				XmlElement isNotNullElement = new XmlElement("if"); //$NON-NLS-1$
				String va = introspectedColumn.getJavaProperty("qo.")
						+ " != null";
				if (introspectedColumn.getJdbcTypeName().equals("VARCHAR")) {
					va += " and " + introspectedColumn.getJavaProperty("qo.")
							+ " != ''";
				}
				isNotNullElement.addAttribute(new Attribute("test", va)); //$NON-NLS-1$ //$NON-NLS-2$
				dynamicElement.addElement(isNotNullElement);

				sb.setLength(0);
				if (introspectedColumn.getJdbcTypeName().equals("VARCHAR")) {
					sb.append(" and "); //$NON-NLS-1$
					sb.append(Ibatis2FormattingUtilities
							.getEscapedColumnName(introspectedColumn));
					sb.append(" like "); //$NON-NLS-1$
					sb.append("CONCAT(CONCAT('%', "); //$NON-NLS-1$
					sb.append(MyBatis3FormattingUtilities.getParameterClause(
							introspectedColumn, "qo."));
					sb.append(" ),'%')"); //$NON-NLS-1$
				} else {
					sb.append(" and "); //$NON-NLS-1$
					sb.append(Ibatis2FormattingUtilities
							.getEscapedColumnName(introspectedColumn));
					sb.append(" = "); //$NON-NLS-1$
					sb.append(MyBatis3FormattingUtilities.getParameterClause(
							introspectedColumn, "qo."));
				}
				isNotNullElement.addElement(new TextElement(sb.toString()));
			}else {//cjianquan 2020/2/1 时间类型的查询条件
				XmlElement isNotNullElement = new XmlElement("if");
				String va = introspectedColumn.getJavaProperty("qo.")+ "Start != null";

				isNotNullElement.addAttribute(new Attribute("test", va)); //$NON-NLS-1$ //$NON-NLS-2$
				dynamicElement.addElement(isNotNullElement);

				sb.setLength(0);
				sb.append("  <![CDATA[ and date_format("+Ibatis2FormattingUtilities.getEscapedColumnName(introspectedColumn)+",'%Y-%m-%d') >= date_format(#{"+introspectedColumn.getJavaProperty("qo.")+"Start},'%Y-%m-%d') ]]> ");
				isNotNullElement.addElement(new TextElement(sb.toString()));

				XmlElement isNotNullElement2 = new XmlElement("if");
				String va2 = introspectedColumn.getJavaProperty("qo.")+ "End != null";

				isNotNullElement2.addAttribute(new Attribute("test", va2)); //$NON-NLS-1$ //$NON-NLS-2$
				dynamicElement.addElement(isNotNullElement2);

				sb.setLength(0);
				sb.append("  <![CDATA[ and date_format("+Ibatis2FormattingUtilities.getEscapedColumnName(introspectedColumn)+",'%Y-%m-%d') <= date_format(#{"+introspectedColumn.getJavaProperty("qo.")+"End},'%Y-%m-%d') ]]> ");
				isNotNullElement2.addElement(new TextElement(sb.toString()));
			}
		}

		//cjianquan 2020/1/2 sqlWhere
		XmlElement isNotNullElement1 = new XmlElement("if"); //$NON-NLS-1$
		String va1 =  " qo.sqlWhere != null";
		va1 += " and qo.sqlWhere != ''";
		isNotNullElement1.addAttribute(new Attribute("test", va1)); //$NON-NLS-1$ //$NON-NLS-2$
		sb.setLength(0);
		sb.append(" <![CDATA[ ${qo.sqlWhere} ]]> ");
		isNotNullElement1.addElement(new TextElement(sb.toString()));
		dynamicElement.addElement(isNotNullElement1);


		/*XmlElement isNotNullElement = new XmlElement("if"); //$NON-NLS-1$
		String va = "qo.beginTime != null";
		isNotNullElement.addAttribute(new Attribute("test", va)); //$NON-NLS-1$ //$NON-NLS-2$
		dynamicElement.addElement(isNotNullElement);
		sb.setLength(0);
		sb.append("<!--%Y-%m-%d %H:%i:%s-->\n");
		sb.append("  <![CDATA[ and date_format(createTime,'%Y-%m-%d') >= date_format(#{qo.beginTime},'%Y-%m-%d') ]]> ");
		isNotNullElement.addElement(new TextElement(sb.toString()));

		isNotNullElement = new XmlElement("if"); //$NON-NLS-1$
		va = "qo.endTime != null";
		isNotNullElement.addAttribute(new Attribute("test", va)); //$NON-NLS-1$ //$NON-NLS-2$
		dynamicElement.addElement(isNotNullElement);
		sb.setLength(0);
		sb.append("  <![CDATA[  and date_format(createTime,'%Y-%m-%d') <= date_format(#{qo.endTime},'%Y-%m-%d') ]]> ");
		isNotNullElement.addElement(new TextElement(sb.toString()));*/
		document.getRootElement().getElements().remove(2);
		return true;
	}

	@Override
	public boolean sqlMapSelectByExampleWithoutBLOBsElementGenerated(
			XmlElement element, IntrospectedTable introspectedTable) {
		if (databaseType.contains("oracle")) {
			XmlElement oracleHeadIncludeElement = new XmlElement("include");
			oracleHeadIncludeElement.addAttribute(new Attribute("refid",
					"common.Oracle_Pagination_Head"));
			// 在第一个地方增加
			element.addElement(0, oracleHeadIncludeElement);

			XmlElement oracleTailIncludeElement = new XmlElement("include");
			oracleTailIncludeElement.addAttribute(new Attribute("refid",
					"common.Oracle_Pagination_Tail"));
			// 在最后增加
			element.addElement(element.getElements().size(),
					oracleTailIncludeElement);
		} else if (databaseType.contains("mysql")) {
			// XmlElement mysqlLimitIncludeElement = new XmlElement("include");
			// mysqlLimitIncludeElement.addAttribute(new Attribute("refid",
			// "common.Mysql_Pagination_Limit"));
			// 在最后增加
			// element.addElement(element.getElements().size(),
			// mysqlLimitIncludeElement);
		}
		return true;
	}

	@Override
	public boolean sqlMapSelectByExampleWithBLOBsElementGenerated(
			XmlElement element, IntrospectedTable introspectedTable) {
		if (databaseType.contains("oracle")) {
			XmlElement oracleHeadIncludeElement = new XmlElement("include");
			oracleHeadIncludeElement.addAttribute(new Attribute("refid",
					"common.Oracle_Pagination_Head"));
			// 在第一个地方增加
			element.addElement(0, oracleHeadIncludeElement);

			XmlElement oracleTailIncludeElement = new XmlElement("include");
			oracleTailIncludeElement.addAttribute(new Attribute("refid",
					"common.Oracle_Pagination_Tail"));
			// 在最后增加
			element.addElement(element.getElements().size(),
					oracleTailIncludeElement);
		} else if (databaseType.contains("mysql")) {
			// XmlElement mysqlLimitIncludeElement = new XmlElement("include");
			// mysqlLimitIncludeElement.addAttribute(new Attribute("refid",
			// "common.Mysql_Pagination_Limit"));
			// 在最后增加
			// element.addElement(element.getElements().size(),
			// mysqlLimitIncludeElement);
		}
		return true;
	}

	@Override
	public List<GeneratedXmlFile> contextGenerateAdditionalXmlFiles(
			IntrospectedTable introspectedTable) {
		Document document = new Document(
				XmlConstants.MYBATIS3_MAPPER_PUBLIC_ID,
				XmlConstants.MYBATIS3_MAPPER_SYSTEM_ID);
		XmlElement answer = new XmlElement("mapper"); //$NON-NLS-1$
		document.setRootElement(answer);
		answer.addAttribute(new Attribute("namespace", //$NON-NLS-1$
				"common"));

		if (databaseType.contains("oracle")) {
			answer.addElement(getOracleHead());
			answer.addElement(getOracleTail());
		} else if (databaseType.contains("mysql")) {
			answer.addElement(getMysqlLimit());
		}

		GeneratedXmlFile gxf = new GeneratedXmlFile(document,
				properties.getProperty("fileName", "common_SqlMap.xml"), //$NON-NLS-1$ //$NON-NLS-2$
				context.getSqlMapGeneratorConfiguration().getTargetPackage(), //$NON-NLS-1$
				context.getSqlMapGeneratorConfiguration().getTargetProject(), //$NON-NLS-1$
				false);

		List<GeneratedXmlFile> files = new ArrayList<GeneratedXmlFile>(1);
		// files.add(gxf);
		return files;
	}

	private XmlElement getOracleHead() {
		XmlElement answer = new XmlElement("sql"); //$NON-NLS-1$

		answer.addAttribute(new Attribute("id", "Oracle_Pagination_Head")); //$NON-NLS-1$

		XmlElement outerisNotEmptyElement = new XmlElement("if");
		outerisNotEmptyElement.addAttribute(new Attribute("test",
				"oracleStart != null and oracleEnd != null"));
		outerisNotEmptyElement
				.addElement(new TextElement(
						"<![CDATA[ select * from ( select row_.*, rownum rownum_ from ( ]]>"));
		answer.addElement(outerisNotEmptyElement);
		return answer;
	}

	private XmlElement getOracleTail() {
		XmlElement answer = new XmlElement("sql"); //$NON-NLS-1$

		answer.addAttribute(new Attribute("id", "Oracle_Pagination_Tail")); //$NON-NLS-1$

		XmlElement outerisNotEmptyElement = new XmlElement("if");
		outerisNotEmptyElement.addAttribute(new Attribute("test",
				"oracleStart != null and oracleEnd != null"));
		outerisNotEmptyElement
				.addElement(new TextElement(
						"<![CDATA[ ) row_ where rownum <= #{oracleEnd} ) where rownum_ > #{oracleStart} ]]>"));
		answer.addElement(outerisNotEmptyElement);
		return answer;
	}

	private XmlElement getMysqlLimit() {
		XmlElement answer = new XmlElement("sql"); //$NON-NLS-1$

		answer.addAttribute(new Attribute("id", "Mysql_Pagination_Limit")); //$NON-NLS-1$

		XmlElement outerisNotEmptyElement = new XmlElement("if");
		outerisNotEmptyElement.addAttribute(new Attribute("test",
				"mysqlOffset != null and mysqlLength != null"));
		outerisNotEmptyElement.addElement(new TextElement(
				"<![CDATA[ limit #{mysqlOffset} , #{mysqlLength} ]]>"));
		answer.addElement(outerisNotEmptyElement);
		return answer;
	}

	@Override
	public List<GeneratedJavaScriptFile> contextGenerateAdditionalJavaScriptFiles() {
		// TODO Auto-generated method stub
		List<GeneratedJavaScriptFile> files = new ArrayList<GeneratedJavaScriptFile>(
				1);
		return files;
	}

	@Override
	public List<GeneratedJavaScriptFile> contextGenerateAdditionalJavaScriptFiles(
			IntrospectedTable introspectedTable) {
		List<GeneratedJavaScriptFile> files = new ArrayList<GeneratedJavaScriptFile>(
				1);
		return files;
	}
}
